package tij4.concurrent.source;

/*
    同步队列
    为什么使用同步队列:
        wait()和notifyAll()方法以一种非常低级的方式解决了任务的互相操作问题,
        即每次交互的时候都握手.在许多情况下可以使用更高级的抽象同步队列.
    同步队列:在任何时刻都只运行一个任务插入或移除元素.
    如果消费者试图从队列中获取对象,而该队列此时为空,那么这些队列还可以挂起消费者任务,'
    并且当有更多的元素可用时恢复消费者任务.
 */

import tij4.concurrent.pojo.LiftOff;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.SynchronousQueue;

class LiftOffRunner implements Runnable {
    private BlockingQueue<LiftOff> rockets;

    public LiftOffRunner(BlockingQueue<LiftOff> rockets) {
        this.rockets = rockets;
    }
    public void add(LiftOff liftOff) {
        try {
            rockets.put(liftOff);
        }catch (InterruptedException e) {
            System.out.println("Interrupted during put()");
        }
    }

    @Override
    public void run() {
        try {
            while (!Thread.interrupted()) {
                LiftOff liftOff = rockets.take();
                liftOff.run();  //使用此线程
            }
        }catch (InterruptedException e) {
            System.out.println("Waking from take()");
        }
        System.out.println("Exiting LiftOffRunner");
    }
}
public class TestBlockQueues {
    static void getKey() {
        try {
            new BufferedReader(
                    new InputStreamReader(System.in)
            ).readLine();

        }catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    static void getKey(String msg) {
        System.out.println(msg);
        getKey();
    }
    static void test(String msg, BlockingQueue<LiftOff> queue) {
        System.out.println(msg);
        LiftOffRunner liftOffRunner = new LiftOffRunner(queue);
        Thread thread = new Thread(liftOffRunner);
        thread.start();
        for (int i = 0; i < 5; i++) {
            liftOffRunner.add(new LiftOff(5));
        }
        getKey("Press 'Enter' (" + msg + ")");  //等待用户响应,使程序阻塞
        thread.interrupt();
        System.out.println("Finished " + msg + " test");
    }

    public static void main(String[] args) {
        test("LinkedBlockingQueue", new LinkedBlockingQueue<LiftOff>());
        test("ArrayBlockingQueue", new ArrayBlockingQueue<LiftOff>(3));
        test("SynchronousQueue", new SynchronousQueue<LiftOff>());
    }
}
